#pragma once

#include<iostream>
#include<string>
#include<vector>

template<typename T>
class RingQueue
{
private:
    //减操作
    void P(sem_t &sem)
    {
        sem_wait(&sem);
    }
    //加操作
    void V(sem_t &sem)
    {
        sem_post(&sem);
    }    
public:
    RingQueue(int cap)
    :_cap(cap)
    ,_ring_queue(_cap)
    ,_productor_step(0)
    ,_consumer_step(0)
    {
        sem_init(&_room_sem,0,_cap);
        sem_init(&_data_sem,0,0);
    }
    void Enqueue(const T &in)
    {
        //生产行为
        P(_room_sem);
        //一定有空间
        _ring_queue[_productor_step++]=in;
        _productor_step %=_cap;
        V(_data_sem);
    }
    void Pop(T *out)
    {
        //消费行为
        P(_data_sem);
        *out=_ring_queue[_consumer_step++];
        _consumer_step %=_cap;
        V(_room_sem);
    }
    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);
    }
private:
    vector<T> _ring_queue;
    int _cap;//环形队列的上限

    //生产和消费的下标
    int _productor_step;
    int _consumer_step;

    //定义信号量
    sem_t _room_sem;//生产者所关心的容量
    sem_t _data_sem;//消费者所关心的数据
};